/**
 * This file is part of 1genia trampoline
 * Copyright (C) 2007 1genia (contact@1genia.com)
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; version 3 of the License. 
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details. 
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; see the file COPYING.TXT.  If not,
 * write to the Free Software Foundation, Inc., 51 Franklin Street,
 * Fifth Floor, Boston, MA 02110-1301, USA. 
 **/
package com.genia.toolbox.uml_generator.manager.impl;

import java.io.File;
import java.io.IOException;

import com.genia.toolbox.basics.exception.BundledException;
import com.genia.toolbox.basics.exception.technical.TechnicalIOException;
import com.genia.toolbox.basics.manager.ExceptionManager;
import com.genia.toolbox.constants.client.Charset;
import com.genia.toolbox.uml_generator.bean.ModelGeneratorContext;
import com.genia.toolbox.uml_generator.manager.ModelEnhancer;
import com.genia.toolbox.uml_generator.manager.ModelGenerator;

import de.hunsicker.io.FileFormat;
import de.hunsicker.jalopy.Jalopy;

/**
 * New method to generate the model from the UML datas.
 */
public class ModelGeneratorImpl
    implements ModelGenerator
{

  /**
   * the {@link ModelEnhancer} to use.
   */
  private ModelEnhancer modelEnhancer;

  /**
   * the {@link ModelGenerator} that handles enumerations.
   */
  private ModelGenerator enumerationGenerator;

  /**
   * the {@link ModelGenerator} that handles interfaces.
   */
  private ModelGenerator interfaceGenerator;

  /**
   * the {@link ModelGenerator} that handles classes.
   */
  private ModelGenerator classGenerator;

  /**
   * the {@link ModelGenerator} to generate hibernate mappings.
   */
  private ModelGenerator hibernateMappingGenerator;

  /**
   * the {@link ModelGenerator} to generate spring related elements.
   */
  private ModelGenerator springGenerator;

  /**
   * the {@link ModelGenerator} to generate dependencies related elements.
   */
  private ModelGenerator dependencyGenerator;

  /**
   * the {@link ExceptionManager} to use.
   */
  private ExceptionManager exceptionManager;



  /**
   * the generator.
   * 
   * @param context
   *          the context of the generation
   * @throws BundledException
   *           when an error occurred
   * @see com.genia.toolbox.uml_generator.manager.ModelGenerator#generate(com.genia.toolbox.uml_generator.bean.ModelGeneratorContext)
   */
  public void generate(ModelGeneratorContext context)
      throws BundledException
  {
    getModelEnhancer().enhanceModel(context);
    getEnumerationGenerator().generate(context);
    getInterfaceGenerator().generate(context);
    getClassGenerator().generate(context);
    getHibernateMappingGenerator().generate(context);
    getDependencyGenerator().generate(context);
    getSpringGenerator().generate(context);
    formatCode(context);
  }



  /**
   * getter for the modelEnhancer property.
   * 
   * @return the modelEnhancer
   */
  public ModelEnhancer getModelEnhancer()
  {
    return modelEnhancer;
  }



  /**
   * setter for the modelEnhancer property.
   * 
   * @param modelEnhancer
   *          the modelEnhancer to set
   */
  public void setModelEnhancer(ModelEnhancer modelEnhancer)
  {
    this.modelEnhancer = modelEnhancer;
  }



  /**
   * getter for the enumerationGenerator property.
   * 
   * @return the enumerationGenerator
   */
  public ModelGenerator getEnumerationGenerator()
  {
    return enumerationGenerator;
  }



  /**
   * setter for the enumerationGenerator property.
   * 
   * @param enumerationGenerator
   *          the enumerationGenerator to set
   */
  public void setEnumerationGenerator(ModelGenerator enumerationGenerator)
  {
    this.enumerationGenerator = enumerationGenerator;
  }



  /**
   * format the generated code.
   * 
   * @param context
   *          the context of the generation
   * @throws TechnicalIOException
   *           when an I/O error occurred
   */
  private void formatCode(ModelGeneratorContext context)
      throws TechnicalIOException
  {
    try {
      if (context.getConfiguration().getJalopyConfiguration() == null) {
        return;
      }
      Jalopy.setConvention(context.getConfiguration().getJalopyConfiguration());
      Jalopy jalopy = new Jalopy();
      jalopy.setEncoding(Charset.UTF8);
      jalopy.setFileFormat(FileFormat.AUTO);
      jalopy.setBackup(false);
      jalopy.setForce(true);
      jalopy.setInspect(false);
      for (File file : context.getGeneratedSources()) {
        jalopy.setInput(file);
        jalopy.setOutput(file);
        boolean success = jalopy.format();
        if (jalopy.getState() == Jalopy.State.ERROR || !success) {
          throw new IOException("Unable to format file: " + file);
        }
      }
    }
    catch (IOException e) {
      throw getExceptionManager().convertException(e);
    }
  }



  /**
   * getter for the interfaceGenerator property.
   * 
   * @return the interfaceGenerator
   */
  public ModelGenerator getInterfaceGenerator()
  {
    return interfaceGenerator;
  }



  /**
   * setter for the interfaceGenerator property.
   * 
   * @param interfaceGenerator
   *          the interfaceGenerator to set
   */
  public void setInterfaceGenerator(ModelGenerator interfaceGenerator)
  {
    this.interfaceGenerator = interfaceGenerator;
  }



  /**
   * getter for the classGenerator property.
   * 
   * @return the classGenerator
   */
  public ModelGenerator getClassGenerator()
  {
    return classGenerator;
  }



  /**
   * setter for the classGenerator property.
   * 
   * @param classGenerator
   *          the classGenerator to set
   */
  public void setClassGenerator(ModelGenerator classGenerator)
  {
    this.classGenerator = classGenerator;
  }



  /**
   * getter for the hibernateMappingGenerator property.
   * 
   * @return the hibernateMappingGenerator
   */
  public ModelGenerator getHibernateMappingGenerator()
  {
    return hibernateMappingGenerator;
  }



  /**
   * setter for the hibernateMappingGenerator property.
   * 
   * @param hibernateMappingGenerator
   *          the hibernateMappingGenerator to set
   */
  public void setHibernateMappingGenerator(ModelGenerator hibernateMappingGenerator)
  {
    this.hibernateMappingGenerator = hibernateMappingGenerator;
  }



  /**
   * getter for the springGenerator property.
   * 
   * @return the springGenerator
   */
  public ModelGenerator getSpringGenerator()
  {
    return springGenerator;
  }



  /**
   * setter for the springGenerator property.
   * 
   * @param springGenerator
   *          the springGenerator to set
   */
  public void setSpringGenerator(ModelGenerator springGenerator)
  {
    this.springGenerator = springGenerator;
  }



  /**
   * getter for the dependencyGenerator property.
   * 
   * @return the dependencyGenerator
   */
  public ModelGenerator getDependencyGenerator()
  {
    return dependencyGenerator;
  }



  /**
   * setter for the dependencyGenerator property.
   * 
   * @param dependencyGenerator
   *          the dependencyGenerator to set
   */
  public void setDependencyGenerator(ModelGenerator dependencyGenerator)
  {
    this.dependencyGenerator = dependencyGenerator;
  }



  /**
   * getter for the exceptionManager property.
   * 
   * @return the exceptionManager
   */
  public ExceptionManager getExceptionManager()
  {
    return exceptionManager;
  }



  /**
   * setter for the exceptionManager property.
   * 
   * @param exceptionManager
   *          the exceptionManager to set
   */
  public void setExceptionManager(ExceptionManager exceptionManager)
  {
    this.exceptionManager = exceptionManager;
  }

}
